
//Si data no existe creamos una estructura
if(data == null){
	var data = {
			"fields":{
				"--default":{
					"length":{"min":"","max":"","msg":{"es":"Debe tener una longitud entre $1 y $2 caracteres"}},
					"value":{"min":"","max":"","msg":{"es":"Debe contener un valor entre $1 y $2"}},
					"rules":[],
					"html":{"hwidth":"","hclass":"","remote":"","jsfunction":"","required":{"enabled":"false","msg":{"es":"Campo requerido"}}},
					"php":{"pfunction":"","required":{"enabled":"false","msg":{"es":"Campo requerido"}}}
				}
			},
			"rules":{},
			"forms":{}
		};
}
////////////////////////// FUNCIONES DE EDICIÓN /////////////////////////////

//Esta función edita una regla
function editarRegla(name){
	borrarTodo('#edicionRegla');
	if(name == false){
		 name = '';
		 rule = new Object(); //Si es una nueva regla su estructura será la estructura por defecto
		 $('#edicionRegla').dialog("option", "title", "Creación de una nueva regla");
	}else{
		rule = data.rules[name];
		$('#edicionRegla').dialog("option", "title", "Edición de la regla "+name);
		//Ajustamos los valores de los campos
		$('#ruleName').val(name);
		$('#regExp').val(rule.data);
		loadmessages($('#rulesMsg'),rule.msg); //Cargamos el selector de mensajes
	}
	//mostramos el formulario
	$('#edicionRegla').dialog('open');
}

//Edita o crea un nuevo campo
function editarCampo(name){
	borrarTodo('#edicionNombre');
	if(name == false){
		 name = '';
		 nameRule = new Object();
		 $('#edicionNombre').dialog("option", "title", "Creación de un nuevo campo");
	}else{
		nameRule = data.fields[name];
		$('#edicionNombre').dialog("option", "title", "Edición del campo "+name);
		$('#fieldName').val(name);	
		$('#minLength').val(nameRule.length.min);	
		$('#maxLength').val(nameRule.length.max);		
		loadmessages($('#lengthMessages'),nameRule.length.msg); //Cargamos el selector de mensajes
		$('#numericOptions').show();
		
		if(nameRule.value.min || nameRule.value.max || name == '--default'){
			if(name == '--default') $('#numericOptions').hide();
			$('#numericYes').attr('checked',true);
			$('#minValue').val(nameRule.value.min);		
			$('#maxValue').val(nameRule.value.max);		
			$('.numeric').show();
		}else{
			$('.numeric').hide();
			$('#numericNo').attr('checked',true);
		}
		loadmessages($('#valueMessages'),nameRule.value.msg); //Cargamos el selector de mensajes	
		$('#htmlWidth').val(nameRule.html.hwidth);	
		$('#htmlClasses').val(nameRule.html.hclass);			
		
		//Checkboxes remote
		if(nameRule.html.remote == 'onkeyup'){
			$('#htmlRemoteKeyUp').attr('checked',true);
		}else if(nameRule.html.remote == 'onfocusout'){
			$('#htmlRemoteFocusOut').attr('checked',true);
		}else{
			$('#htmlRemoteNo').attr('checked',true);
		}
		if(nameRule.html.required.enabled == 'true'){
			$('#htmlRequired').attr('checked',true);
		}else{
			$('#htmlRequired').attr('checked',false);
		}
		loadmessages($('#requiredMessages'),nameRule.html.required.msg); //Cargamos el selector de mensajes			
		if(nameRule.php.required.enabled == 'true'){
			$('#phpRequired').attr('checked',true);
		}else{
			$('#phpRequired').attr('checked',false);
		}
		loadmessages($('#phprequiredMessages'),nameRule.php.required.msg); //Cargamos el selector de mensajes	
		$('#jsFunction').val(nameRule.html.jsfunction);
		$('#phpFunction').val(nameRule.php.pfunction);
		
		//Selectores de reglas
		$.each(nameRule.rules,function(index, value) {
			if(value != '') $('#fieldRules').append('<option value="'+value+'">'+value+'</option>');
		});
	}
	$.each(data.rules,function(index, value) {
		if(!$("#fieldRules option[value='"+index+"']").text()) $('#currentRules').append('<option value="'+index+'">'+index+'</option>');
	});	
	$('#edicionNombre').dialog('open');
}

//Esta función edita una regla
function editarForm(name){
	borrarTodo('#edicionFormulario');
	if(name == false){
		 name = '';
		 form = new Object(); //Si es una nueva regla su estructura será la estructura por defecto
		 $('#edicionFormulario').dialog("option", "title", "Creación de un nuevo formulario");
	}else{
		form = data.forms[name];
		 $('#edicionFormulario').dialog("option", "title", "Edición del formulario "+name);
		//Ajustamos los valores de los campos
		$('#formName').val(name);
		//Rellenamos lso campos seleccionados
		$.each(form,function(index, value) {
			if(value != '') $('#formFields').append('<option value=\''+value+'\'>'+value+'</option>');
		});
	}	
		$.each(data.fields,function(index, value) {
			//if(value.php.required.enabled != 'true') return true; //Sólo incluimos los requeridos..
			if(index == '--default') return true; //Continue
			if(!$("#formFields option[value='"+index+"']").text()) $('#currentFields').append('<option value=\''+index+'\'>'+index+'</option>');
		});	
	//mostramos el formulario
	$('#edicionFormulario').dialog('open');
}

//Esta función crea un nuevo mensaje de error
function nuevoMensaje(element,aditionaltext){
	var idioma = prompt("Introduzca el idioma para el que va a escribir el mensaje.\n\n Ej: \"es\" \"es-Es\" \"Es-Ca\"","");
	if(/^[a-zA-Z]{2}(-[a-zA-Z]{2})?$/.test(idioma) && $(element).find('[lang="'+idioma+'"]').length == 0){ //Comprobamos que tenga el formato correcto y que no exista en la lista
	 	var texto = prompt("Introduzca el texto del mensaje.                                                                     \n\n"+aditionaltext,"");
	 	texto = texto.replace(/\"/g,"&quot;");
	 	if(texto != '') $(element).append('<option lang="'+idioma+'" value="'+texto+'">['+idioma+'] '+texto+'</option>')
	 }else{
		alert("El idioma introducido no tiene un formato correcto o ya existe.");
		return false;
	}
}

//Esta función edita un mensaje de error
function editarMensaje(element,aditionaltext){
	var idiomaOld = $(element).find(':selected').attr('lang');
	var valOld = $(element).find(':selected').attr('value');
	if(idiomaOld == null) return false;
	var idioma = prompt("Idioma para el del mensaje.\n\n  Ej: \"es\" \"es-Es\" \"Es-Ca\"",idiomaOld);
	if(/^[a-zA-Z]{2}(-[a-zA-Z]{2})?$/.test(idioma) && $(element).find('[lang="'+idioma+'"]:not(:selected)').length == 0){ //Comprobamos que tenga el formato correcto y que no exista en la lista des los no seleccionados (El selecionado siempre existe)
	 	var texto = prompt("Texto del mensaje (Para eliminar el mensaje déjelo en blanco).                                      \n\n"+aditionaltext,valOld);
	 	texto = texto.replace(/\"/g,"&quot;");
	 	$(element).find(':selected').remove();
	 	if(texto != '') $(element).append('<option lang="'+idioma+'" value="'+texto+'">['+idioma+'] '+texto+'</option>')
	 }else{
		alert("El idioma introducido no tiene un formato correcto o ya existe.");
		return false;
	}
}

///////////////////////////////// FUNCIONES DE GUARDADO //////////////////////////////

function guardarRegla(){
	//VALIDACIONES PRE GUARDADO
	var name = $('#ruleName').val();
	if(!/^\w{3,}$/.test(name)){ alert('El nombre de la regla debe ser alfanumérico, sin espacios y tener más de 3 caracteres'); return false; }
	var regexp = $('#regExp').val();
	if(!/^[^/ ].{3,}[^/ ]$/.test(regexp)){ alert('La expresión regular debe tener más de 3 caracteres y no puede empezar ni terminar por / o espacios'); return false; }
	
	//SI LAS VALIACIONES HAN SIDO CORRECTAS CONTINUAMOS
	var rule = new Object();
	rule.data = regexp;
	rule.msg = new Object();
	//Para cada mensaje del select introducimos el mensaje en data
	$.each($('#rulesMsg option'),function(index, option) {
		rule.msg[$(option).attr('lang')] = $(option).val();
	});
	rule.msg = sortObject(rule.msg); //Ordenamos los mensajes antes de guardarlos
	data.rules[name] = rule;
	//Ocultamos el formulario
	$('#edicionRegla').dialog('close');	
	actualizarTablaReglas();
}

function guardarField(){
	var field = {"length":{"msg":{}},"value":{"msg":{}},"html":{"required":{"msg":{}}},"rules":[],"php":{"required":{"msg":{}}}}
	//VALIDACIONES PRE GUARDADO
	var name = $('#fieldName').val();
	if(!/^\w+((\[\"\w+\"\])|(\[\]))?$/.test(name) && name != '--default'){ alert('El nombre del campo debe ser alfanumérico y sin espacios.\n\n Ej: userName user[\"name\"] userName[]'); return false; }
	field.length.min = $('#minLength').val();	
	field.length.max = $('#maxLength').val();	
	if(!/^\d*$/.test(field.length.min) || !/^\d*$/.test(field.length.max)){ alert('Longitud máxima y mínima deben ser numéricos sin espacios o estar vacíos'); return false; }
	if(parseInt(field.length.min) > parseInt(field.length.max)){ alert('Longitud máxima debe ser mayor a la mínima'); return false; }
	if($('#numericYes').attr('checked')){
		field.value.min = $('#minValue').val();
		field.value.max = $('#maxValue').val();
		if(!/^(\d+(\.\d+)?)?$/.test(field.value.min) || !/^(\d+(\.\d+)?)?$/.test(field.value.max)){ alert('Valor máximo y mínimo deben ser numéricos sin espacios\nPuede usar . como separador de decimales pero no ,'); return false; }
		if(parseFloat(field.value.min) > parseFloat(field.value.max)){ alert('Valor máximo debe ser mayor al mínimo'); return false; }
	}else{
		field.value.min = '';
		field.value.max = '';
	}
	field.html.hwidth =	$('#htmlWidth').val();
	if(!/^\d*((em)|(px)|(%))?$/.test(field.html.hwidth)){ alert('La anchura del campo debe ser numérico seguido de px, em o % sin espacios.'); return false; }
	field.html.hclass =	$('#htmlClasses').val();
	if(!/^\w*(\s+\w*)*$/.test(field.html.hclass)){ alert('Las clases a aplicar deben contener sólo alfanuméricos separadas por espacios'); return false; }
	field.html.jsfunction = $('#jsFunction').val();
	if(!/^\w*$/.test(field.html.jsfunction)){ alert('La funcion js debe ser únicamente un nombre de función alfanúmerico sin espacios, después se la llamará pasándole los parámetros indicados en  el manual.\n Ej: mifuncion'); return false; }
	field.php.pfunction = $('#phpFunction').val();
	if(!/^\w*$/.test(field.php.pfunction)){ alert('La funcion php debe ser únicamente un nombre de función alfanúmerico sin espacios, después se la llamará pasándole los parámetros indicados en  el manual.\n Ej: mifuncion'); return false; }
	//SI LAS VALIACIONES HAN SIDO CORRECTAS CONTINUAMOS
	
	if($('#htmlRemoteKeyUp').attr('checked')){
		field.html.remote = 'onkeyup';
	}else if($('#htmlRemoteFocusOut').attr('checked')){
		field.html.remote = 'onfocusout';
	}else{
		field.html.remote = 'none';
	}
	if($('#htmlRequired').attr('checked')){
		field.html.required.enabled = 'true';
	}else{
		field.html.required.enabled = 'false';
	}
	if($('#phpRequired').attr('checked')){
		field.php.required.enabled = 'true';
	}else{
		field.php.required.enabled = 'false';
	}	
	//Tratamiento de los mensajes de cada campo
	$.each($('#lengthMessages option'),function(index, option) {
		field.length.msg[$(option).attr('lang')] = $(option).val();
	});
	$.each($('#valueMessages option'),function(index, option) {
		field.value.msg[$(option).attr('lang')] = $(option).val();
	});	
	$.each($('#requiredMessages option'),function(index, option) {
		field.html.required.msg[$(option).attr('lang')] = $(option).val();
	});		
	$.each($('#phprequiredMessages option'),function(index, option) {
		field.php.required.msg[$(option).attr('lang')] = $(option).val();
	});	
	$('#fieldRules option').each(function(i) {
		field.rules[i] = $(this).val();
	});
	data.fields[name] = field;
	actualizarTablaFields();
	$('#edicionNombre').dialog('close');
}

function guardarFormulario(){
	//VALIDACIONES PRE GUARDADO
	var name = $('#formName').val();
	if(!/^\w{3,}$/.test(name)){ alert('El nombre del formulario debe ser alfanumérico, sin espacios y tener más de 3 caracteres'); return false; }
	
	
	//SI LAS VALIACIONES HAN SIDO CORRECTAS CONTINUAMOS
	var form = new Array();
	$('#formFields option').each(function(i) {
		form.push($(this).val());
	});
	data.forms[name] = form;
	actualizarTablaForms();
	$('#edicionFormulario').dialog('close');
}

///////////////////////////// FUNCIONES DE BORRADO //////////////////////////////////////

function borrarRegla(elem){
	if(confirm('¿Está seguro de que desea eliminar esta regla?\n\nNo olvide cambiar los nombres que la estuviesen utilizando')){
		 var name = $(elem).closest('tr').attr('id');
		 delete data.rules[name];
		 actualizarTablaReglas();
	}
}

function borrarField(elem){
	if(confirm('¿Está seguro de que desea eliminar este nombre?')){
		 var name = $(elem).closest('tr').attr('id');
		 delete data.fields[name];
		 actualizarTablaFields();
	}
}

function borrarForm(elem){
	if(confirm('¿Está seguro de que desea eliminar este formulario?')){
		 var name = $(elem).closest('tr').attr('id');
		 delete data.forms[name];
		 actualizarTablaForms();
	}
}

//////////////////////////////// FUNCIONES DE MOSTRADO DE TABLAS ////////////////////////

function actualizarTablaReglas(){
	$('#tablaReglas tbody').html('');
	loadRules();
}

function actualizarTablaFields(){
	$('#tablaNombres tbody').html('');
	loadFields();
}

function actualizarTablaForms(){
	$('#tablaForms tbody').html('');
	loadForms();
}

function loadRules(){
	var result = false;
	data.rules = sortObject(data.rules);
	var rules = data.rules;
	$.each(rules,function(index, value) {
		  var nombre = index;
		  var row = '<tr id="'+nombre+'">'+
		      		'<td style="padding-left:5px;"><a onclick="borrarRegla(this);" title="Eliminar esta regla" style="cursor:pointer;">[D]</a> <a onclick="editarRegla(\''+nombre+'\')" title="Modificar regla" style="cursor:pointer;">[M]</a></td>'+
		    		'<td>'+nombre+'</td>'+
		    		'<td align="center">'+value.data+'</td>'+
				  	'</tr>';
				  	
		  $('#tablaReglas > tbody:last').append(row);
		  result = true;
	});
	return result;
}

function loadFields(){
	var result = false;
	data.fields = sortObject(data.fields);
	$.each(data.fields,function(index, field) {
		  var nombre = index;
		  var row = '<tr id="'+nombre+'">'+
		      		'<td style="padding-left:5px;">';
		      		if(nombre != '--default'){ row = row +'<a onclick="borrarField(this);" title="Eliminar este campo" style="cursor:pointer;">[D]</a>'; 
		      		}else{row = row +'<a onclick="alert(\'La opción por defecto se aplicará a todos los campos que no estén definidos en este menú, no puede borrarla pero puede dejar los valores en blanco.\\n\\nNo obstante DEBE CONFIGURAR todos los mensajes de este campo ya que serán los utilizados por defecto en los campos para los que no haya designado ningún mensaje específico.\');">[?]</a>';}
		      		row = row + '<a onclick="editarCampo(\''+nombre.replace('["','\[&quot;').replace('"]','&quot;\]')+'\')" title="Modificar este campo" style="cursor:pointer;">[M]</a></td>'+
		    		'<td>'+nombre+'</td>'+
		    		'<td align="center">';
		    		$.each(field.rules,function(index2, value2) {
			    		row=row+value2+',';
		    		});
		    		row = row+'</td>'+ 
		    		'<td align="center">Min:'+field.length.min+' Max:'+field.length.max+'</td>'+
		    		'<td align="center">Min:'+field.value.min+' Max:'+field.value.max+'</td>'+
		    		'<td align="center">width:'+field.html.hwidth+' remote:['+field.html.remote+']'; 
		    		if(field.html.required.enabled == 'true') row = row +' -required- '; 
		    		row = row+'<div> clases:['+field.html.hclass+'] func:'+field.html.jsfunction+'</div></td><td align="center">';
		    		if(field.php.required.enabled == 'true') row = row +' -required- ';
		    		row = row+'<div>func:'+field.php.pfunction+'</div></td></tr>';
		  $('#tablaNombres > tbody:last').append(row);
		  result = true;
	});
	return result;
}

function loadForms(){
	var result = false;
	data.forms = sortObject(data.forms);
	$.each(data.forms,function(index, value) {
		  var nombre = index;
		  var row = '<tr id="'+nombre+'">'+
		      		'<td style="padding-left:5px;"><a onclick="borrarForm(this);" title="Eliminar este formulario" style="cursor:pointer;">[D]</a> <a onclick="editarForm(\''+nombre+'\')" title="Modificar formulario" style="cursor:pointer;">[M]</a></td>'+
		    		'<td>'+nombre+'</td>'+
		    		'<td align="center">';
		    		$.each(value,function(index2, value2) {
			    		row=row+value2+',';
		    		});
		    		row = row+'</td></tr>';
				  	
		  $('#tablaForms > tbody:last').append(row);
		  result = true;
	});
	return result;
}

/////////////////////////////////////////// OTRAS FUNCIONES ////////////////////////////////////

//Ordena un objeto por sus indices primarios
function sortObject(obj) {
	var indice = [];
	var newdata = new Object();
	//Obtenemos los índices y los ordenamos
	$.each(obj,function(index, value) {
		indice.push(index);
	});
	indice.sort(function(a,b) {
	    a = a.toLowerCase();
	    b = b.toLowerCase();
	    if( a == b) return 0;
	    if( a > b) return 1;
	    return -1;
	});
	$.each(indice,function(index, value) {
		newdata[value] = obj[value];
	});
	return newdata;
}

//Codifica el nombre de los elementos para evitar problemas
function parsename(element){
	var name = $(element).attr('name').replace('[','["').replace(']','"]');
	return name;
}

//Carga un selector de mensajes
function loadmessages(element,messages){
	$(element).empty(); //Vaciamos el select
	$.each(messages,function(index, value){
		$(element).append('<option lang="'+index+'" value="'+value+'">['+index+'] '+value+'</option>');
	});
}

function moveRules(from,to){
	$(from).find(":selected").each(function(i,selected){
		var value = $(selected).text().replace('["','\[&quot;').replace('"]','&quot;\]');
		$(to).append('<option value="'+value+'">'+value+'</option>');
    });
    $(from).find(":selected").remove();	
}

function moveUpRule(){
	$('#fieldRules option:selected').each(function(){
		$(this).insertBefore($(this).prev());
	});
}

function moveDownRule(){
	$('#fieldRules option:selected').each(function(){
			$(this).insertAfter($(this).next());
	 });
} 

function moveUpField(){
	$('#formFields option:selected').each(function(){
		$(this).insertBefore($(this).prev());
	});
}

function moveDownField(){
	$('#formFields option:selected').each(function(){
			$(this).insertAfter($(this).next());
	 });
} 

function borrarTodo(container){
	 $.each($(container).find('input:text'),function(index,input) {
		$(input).val('');
	});
	$.each($(container).find('select'),function(index,input) {
		$(input).empty();
	});
}

//Envía el formulario
function generateFile(){
	data.info = "Created with jpvalidator. Jpvalidator is a free php&Jquery validator created by Carlos Mora Molina on November 2012. Version 2.0"
	$('#jsonData').val(JSON.stringify(data));
	$('#saveFile').submit();
}
